Improving Error Handling

The previous topics have concentrated on “happy path” customization. You can also customize the property grid to provide more informative error handling.

Modifying a Custom Editor

For properties where you are supplying a custom editor, you can create your error handling user interface as part of your template. The following code shows the “feet and inches” editor extended to display validation errors using a tooltip and a popup.

CopyFeet and inches editor with validation
<DataTemplate x:Key='FeetAndInchesEditorWithValidation'>
    <ms:TextBox BorderThickness='0' Text='{Binding Value, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource FeetAndInchesConverter}, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}' Style='{StaticResource TextBoxStandardErrorHandling}'>
    </ms:TextBox>
  </DataTemplate>

CopyCommon style for text boxes that handle validation errors
<Style TargetType='{x:Type ms:TextBox}' x:Key='TextBoxStandardErrorHandling'>
    <Setter Property='Control.Template'>
      <Setter.Value>
        <ControlTemplate TargetType='{x:Type ms:TextBox}'>
          <DockPanel>
            <ToggleButton x:Name='ErrorPlaceholder' Style='{StaticResource ErrorPopupTriggerStyle}'/>
            <Popup PlacementTarget='{Binding ElementName=ErrorPlaceholder}' AllowsTransparency='True' StaysOpen='False' Placement='Bottom' IsOpen='{Binding ElementName=ErrorPlaceholder, Path=IsChecked}'>
              <ItemsControl ItemTemplate='{StaticResource ValidationErrorMessage}' ItemsSource='{Binding RelativeSource={RelativeSource AncestorType={x:Type ms:TextBox}}, Path=(Validation.Errors)}'/>
            </Popup>
            <ScrollViewer x:Name='PART_ContentHost'/>
          </DockPanel>
          <ControlTemplate.Triggers>
            <Trigger Property='Validation.HasError' Value='True'>
              <Setter TargetName='ErrorPlaceholder' Property='Visibility' Value='Visible'/>
            </Trigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
    <Setter Property='Validation.ErrorTemplate'>
      <Setter.Value>
        <ControlTemplate>
          <DockPanel>
            <Ellipse Margin='0,0,6,0' ToolTip='{Binding ElementName=EditorHolder, Path=AdornedElement.(Validation.Errors)[0], Converter={StaticResource InnerExceptionExtractor}}' Width='8' Height='8' Fill='Red'/>
            <AdornedElementPlaceholder x:Name='EditorHolder'/>
          </DockPanel>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>

If you’re using exceptions to indicate validation failures, you’ll need to use a value converter to ‘unpack’ TargetInvocationExceptions.
 

For property grid validation, it’s often more convenient to use IDataErrorInfo rather than exceptions.
 

Styling a Built-In Editor

For properties where you are using a built-in editor, you can use styling to create your error handling user interface, via the PropertyEditor.Style property.

You can also define error-handling user interfaces to be applied across all instances of the built-in editors, rather than on a property-by-property basis, by using the BuiltInEditorStyles property. This example shows how to add error handling to the textbox editor. Notice that both the FirstName and Surname properties automatically acquire the new style, even though there are no PropertyEditors with custom styles assigned to these two properties.

CopyAdding error handling to the builtin text editor
<ms:PropertyGrid.BuiltInEditorStyles>
        <ms:BuiltInEditorStyleCollection>
          <ms:BuiltInEditorStyle EditorKey='{x:Static ms:PropertyGrid.SimpleTextEditorKey}' Style='{StaticResource TextBoxStandardErrorHandling}'/>
        </ms:BuiltInEditorStyleCollection>
      </ms:PropertyGrid.BuiltInEditorStyles>

See 07_ImprovingErrorHandling.xaml.

Next step: Adding a Description Panel.